package com.sinevil.tcpTrans.entity.json.handlers;


import com.sinevil.tcpTrans.entity.json.FilePacketJson;
import com.sinevil.tcpTrans.entity.json.InstructionJson;
import com.sinevil.tcpTrans.tcp.TCPServerNode;
import com.sinevil.tcpTrans.tcp.TCPTransNode;
import com.sinevil.tcpTrans.utils.fileTrans.FileTranser;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.regex.Matcher;

/**
 * @Classname ServerSocketJsonHandle
 * @Description TODO 服务端 套接字维护
 * @Version 1.0.0
 * @Date 2024/12/12 21:53
 * @Created by sinevil
 */
public class ServerSocketJsonHandle extends SocketJsonHandle {

    protected TCPServerNode serverNode;


    // 通过构造函数注入TCPTransNode实例，从中获取fileInfoMap
    public ServerSocketJsonHandle(TCPServerNode serverNode, FileTranser fileTranser, int buffer_size) {

        super();
        this.fileTranser = fileTranser;
        this.serverNode = serverNode;
        this.BUFFER_SIZE = buffer_size;
        this.readBuffer = ByteBuffer.allocate(buffer_size+256);
        this.writeBuffer = ByteBuffer.allocate(buffer_size+256);

        this.initInstructionHandlersMap();
        this.initFilePacketHandlersMap();

    }

    /**
     *
     * @param serverNode 服务端结点
     */
    public ServerSocketJsonHandle(TCPServerNode serverNode, FileTranser fileTranser) {
        this(serverNode,fileTranser, TCPTransNode.BUFFER_SIZE);
    }

    /**
     * 初始化默认的指令Json数据类对象和处理函数的映射关系
     */
    @Override
    protected void initInstructionHandlersMap(){
        super.initInstructionHandlersMap();
        // 添加共有的指令处理函数
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_FILE_MD5,this::handlePUBLIC_FILE_MD5);

        this.instructionHandlersMap.put(InstructionJson.CLOSE_CONNECT,this::handleCloseConnect);
        this.instructionHandlersMap.put(InstructionJson.ClIENT_REQUEST_FILE, this::handleCLIENT_REQUEST_FILE);
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_FILE_INFO,this::handleCLIENT_UPLOAD_FILE);
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_REQUEST_FILE_PACKET,this::handleCLIENT_REQUEST_FILE_PACKET);
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_REQUEST_FILE_COMPLETE,this::handleClient_COMPLETE_DOWNLOAD_FILE);
        this.instructionHandlersMap.put(InstructionJson.PUBLIC_UPLOAD_ERROR_REQUEST_FILE,this::handlePUBLIC_UPLOAD_ERROR_REQUEST_FILE);
    }

    /**
     * 初始化默认的文件包数据类对象和处理函数的映射关系
     * TODO 对应文件数据包的处理扩展 应更改为针对 数据包json 类型直接获取处理函数，应在JsonHandlersMap中直接添加
     */
    @Override
    protected void initFilePacketHandlersMap() {
        super.initFilePacketHandlersMap();
        // 添加共有的指令处理函数
        this.filePacketHandlersMap.put(FilePacketJson.class,this::handlePUBLIC_ACCEPT_FILE_PACKET);

    }





    /**
     * 服务端 处理关闭连接指令
     *
     * @param instructionJson
     * @param socketChannel
     */
    private void handleCloseConnect(InstructionJson instructionJson, SocketChannel socketChannel){
        try {
            // 关闭SocketChannel连接
            socketChannel.close();

        } catch (IOException e) {
            // TODO e.printStackTrace();
            e.printStackTrace();
        }
    }



    /**
     * 服务端 处理 客户端请求下载文件
     * @param instructionJson 客户端请求下载文件的指令
     * @param socketChannel   套接字
     */
    private void handleCLIENT_REQUEST_FILE(InstructionJson instructionJson, SocketChannel socketChannel){
        String content = instructionJson.getContent();
        Matcher matcher = InstructionJson.ClIENT_REQUEST_FILE_PATTERN.matcher(content);

        if (matcher.find()) {
            String filePath = matcher.group(1);
            try {
                this.fileTranser.addUploadTask(filePath, socketChannel);
            } catch (FileNotFoundException e) {
                this.serverNode.sendMessage(socketChannel, new InstructionJson(InstructionJson.PUBLIC_UPLOAD_ERROR_REQUEST_FILE, String.format(InstructionJson.PUBLIC_UPLOAD_ERROR_REQUEST_FILE_FORMAT, filePath, "文件不存在")));
            }
        }

    }

    /**
     * 服务端 处理 客户端请求文件数据包
     * @param instructionJson
     * @param socketChannel
     */
    private void handleCLIENT_REQUEST_FILE_PACKET(InstructionJson instructionJson, SocketChannel socketChannel){
        String content = instructionJson.getContent();
        Matcher matcher = InstructionJson.PUBLIC_REQUEST_FILE_PACKET_PATTERN.matcher(content);
        if (matcher.find()) {
            this.fileTranser.addUploadPacketRequest(socketChannel, matcher.group(1), Long.parseLong(matcher.group(2)),Integer.parseInt(matcher.group(3)));
        }
    }

    /**
     * 服务端 处理 客户端请求上传文件
     * @param instructionJson 上传文件指令
     * @param socketChannel 客户端套接字
     */
    private void handleCLIENT_UPLOAD_FILE(InstructionJson instructionJson, SocketChannel socketChannel){
        String content = instructionJson.getContent();
        Matcher matcher = InstructionJson.PUBLIC_FILE_INFO_PATTERN.matcher(content);
        if (matcher.find()) {
            String uid = matcher.group(1);
            long size = Long.parseLong(matcher.group(2));
            String fileName = matcher.group(3);
            String path = matcher.group(4);
            // 如果添加任务成功则正常执行，如果失败则返回失败指令
            if (!fileTranser.addDownloadTask(socketChannel,fileName, uid, size, path))
                this.serverNode.sendMessage(socketChannel, new InstructionJson(InstructionJson.SERVER_ERROR_CLIENT_UPLOAD_FILE,content));
        }
    }

    /**
     * 客户端完成文件下载
     * 通知服务端清理资源
     * @param instructionJson 下载文件完成指令
     * @param socketChannel 客户端套接字
     */
    private void handleClient_COMPLETE_DOWNLOAD_FILE(InstructionJson instructionJson, SocketChannel socketChannel){
        String content = instructionJson.getContent();
        Matcher matcher = InstructionJson.PUBLIC_REQUEST_FILE_COMPLETE_PATTERN.matcher(content);
        if (matcher.find()) {
            this.fileTranser.completeUploadTrans(socketChannel, matcher.group(1), Integer.parseInt(matcher.group(2)),matcher.group(3));
        }
    }


}